package com.backend.api.security.jwt;

import com.common.model.Menu;
import com.common.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.*;

/**
 * 权限资源管理器
 * 为权限决断器提供支持
 */
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Autowired
    private MenuService menuService;

    private Map<String, Collection<ConfigAttribute>> map = null;

    /**
     * 加载权限表中所有操作请求权限
     */
    private void loadResourceDefine() {
        map = new HashMap<>(16);
        Collection<ConfigAttribute> configAttributes;
        ConfigAttribute cfg;
        // 获取启用的权限操作请求
        List<Menu> menus = menuService.findAll();
        for (Menu menu : menus) {
            configAttributes = new ArrayList<>();
            cfg = new SecurityConfig(menu.getRequestPerm());
            //作为MyAccessDecisionManager类的decide的第三个参数
            configAttributes.add(cfg);
            //用权限的path作为map的key，用ConfigAttribute的集合作为value
            map.put(menu.getRequestPerm(), configAttributes);
        }
    }

    /**
     * 判定用户请求的url是否在权限表中
     * 如果在权限表中，则返回给decide方法，用来判定用户是否有此权限
     * 如果不在权限表中则放行
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        if (map == null) {
            loadResourceDefine();
        }
        //Object中包含用户请求request
        String url = ((FilterInvocation) o).getRequest().getRequestURI();
        String requestType = ((FilterInvocation) o).getRequest().getMethod();
        String requestPerm = url + " " + requestType;
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String resURL : map.keySet()) {
            if (pathMatcher.match(resURL, requestPerm)) {
                return map.get(resURL);
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}